package edu.stanford.bmir.protege.web.server.stkosutil.enricher.handlers;

import com.google.common.base.Optional;

import edu.stanford.bmir.protege.web.client.dispatch.actions.CreateClassesAction;
import edu.stanford.bmir.protege.web.client.dispatch.actions.CreateClassesResult;
import edu.stanford.bmir.protege.web.client.rpc.data.EntityData;
import edu.stanford.bmir.protege.web.client.rpc.data.SubclassEntityData;
import edu.stanford.bmir.protege.web.client.rpc.data.Triple;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.MatchLevel;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.TripleData;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.UtilConstants;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.UtilEntityType;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.CandidateEntity;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnrichmentResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateCandidateClassesAction;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateCandidateClassesResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateTriplesAction;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateTriplesResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.statistics.StatisticsResult;
import edu.stanford.bmir.protege.web.server.change.ChangeApplicationResult;
import edu.stanford.bmir.protege.web.server.change.ChangeDescriptionGenerator;
import edu.stanford.bmir.protege.web.server.change.CreateClassesChangeGenerator;
import edu.stanford.bmir.protege.web.server.change.FixedMessageChangeDescriptionGenerator;
import edu.stanford.bmir.protege.web.server.dispatch.AbstractHasProjectActionHandler;
import edu.stanford.bmir.protege.web.server.dispatch.ExecutionContext;
import edu.stanford.bmir.protege.web.server.dispatch.RequestContext;
import edu.stanford.bmir.protege.web.server.dispatch.RequestValidator;
import edu.stanford.bmir.protege.web.server.dispatch.validators.UserHasProjectReadPermissionValidator;
import edu.stanford.bmir.protege.web.server.msg.OWLMessageFormatter;
import edu.stanford.bmir.protege.web.server.owlapi.AnnotationsTreatment;
import edu.stanford.bmir.protege.web.server.owlapi.NonAnnotationTreatment;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProject;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProjectManager;
import edu.stanford.bmir.protege.web.server.owlapi.RenderingManager;
import edu.stanford.bmir.protege.web.server.owlapi.TripleMapper;
import edu.stanford.bmir.protege.web.server.owlapi.TripleMapperSelector;
import edu.stanford.bmir.protege.web.server.stkosutil.enricher.CandidateClassHolder;
import edu.stanford.bmir.protege.web.server.stkosutil.enricher.CandidateClassesChangeGenerator;
import edu.stanford.bmir.protege.web.server.stkosutil.enricher.CandidateOPChangeGenerator;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlClassHolder;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlClassHolderComparator;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlDataPropertyHolder;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlDataPropertyHolderComparator;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlObjectPropertyHolder;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlObjectPropertyHolderComparator;
import edu.stanford.bmir.protege.web.server.stkosutil.statistics.EntityCounter;
import edu.stanford.bmir.protege.web.shared.BrowserTextMap;
import edu.stanford.bmir.protege.web.shared.ObjectPath;
import edu.stanford.bmir.protege.web.shared.project.ProjectId;
import edu.stanford.bmir.protege.web.shared.user.UserId;

import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.EntityType;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

	/**
	 * Author: Matthew Horridge<br>
	 * Stanford University<br>
	 * Bio-Medical Informatics Research Group<br>
	 * Date: 22/02/2013
	 */
	public class CreateCandidateTriplesActionHandler{
		
		private ArrayList<OwlClassHolder> _alClassByBT = null;
		private ArrayList<OwlClassHolder> _alClassByLowerBT = null;
		private ArrayList<OwlObjectPropertyHolder> _alObjectProperyByBT = null;
		private ArrayList<OwlObjectPropertyHolder> _alObjectProperyByLowerBT = null;
		private ArrayList<OwlDataPropertyHolder> _alDataProperyByBT = null;
		private ArrayList<OwlDataPropertyHolder> _alDataProperyByLowerBT = null;
		
		private ArrayList<SubclassEntityData> _createdObjectClassList = null;
		private ArrayList<EntityData> _createdObjectPropertyList = null;
		
		private int _newClassCount = 0 ;
		private int _newPropertyCount = 0;
		private int _newClassCurb = 50;
		private int _newPropertyCurb = 50;
		private int _newTriplePerClassCurb = 5;
		
		 private OWLAPIProject getProject(String projectName) {
		        if (projectName == null) {
		            throw new NullPointerException("projectName must not be null");
		        }
		        ProjectId projectId = ProjectId.get(projectName);
		        // TODO: Log
		        return getProject(projectId);
		 }

		    /**
		     * Gets the OWLAPIProject for a given {@link ProjectId}.If a project with the specified id exists then that project
		     * will be returned, otherwise, a fresh project will be created and that fresh project returned.
		     * @param projectId The id of the project.
		     * @return The OWL API project. Not <code>null</code>.
		     */
		 private OWLAPIProject getProject(ProjectId projectId) {
		        OWLAPIProjectManager pm = OWLAPIProjectManager.getProjectManager();
		        return pm.getProject(projectId);
		 }
		 private void createSubclasses(OWLAPIProject project, CreateTriplesAction action,UserId userId, CreateTriplesResult result) {
			 String parentName = action.getEntityName();
		    	ArrayList<SubclassEntityData> subClassEntityDataList = new ArrayList<SubclassEntityData>();
		    	result.setSubClassEntityDataList(subClassEntityDataList);
		    	
		    	RenderingManager rm = project.getRenderingManager();
		 	    OWLClass parentClass= rm.getEntity(parentName, EntityType.CLASS);
		 	   
		 	    OwlClassHolderComparator classComparator = new OwlClassHolderComparator(MatchLevel.CASE_INSENSITIVE);
		 	    ArrayList<CandidateEntity> subclasses = this.extractSubclassCandidates(action.getCandidateTriples());
		 	    for (int i=subclasses.size()-1; i>=0; i--){
		 	    	CandidateEntity subclass = subclasses.get(i);
		 	    	OwlClassHolder classHolderSeed = new OwlClassHolder();
					classHolderSeed.setBrowserText(subclass.getBrowserText());
					int pos = Collections.binarySearch(this._alClassByLowerBT, classHolderSeed, classComparator);
					if (pos>=0){
						subclasses.remove(i);
					}
		 	    }
		 	    
		 	    
		 	    ArrayList<CandidateClassHolder> alCandidateClassHolders = new ArrayList<CandidateClassHolder>();
		 	    CandidateClassHolder candidateClassHolder = new CandidateClassHolder();
		 	    candidateClassHolder.setOwlClass(parentClass);
		 	    candidateClassHolder.setCandidateChildClassList(subclasses);
		 	    alCandidateClassHolders.add(candidateClassHolder);
		 	    CandidateClassesChangeGenerator changeGenerator = new CandidateClassesChangeGenerator(alCandidateClassHolders);
		 		ChangeDescriptionGenerator descriptionGenerator = new FixedMessageChangeDescriptionGenerator("本体丰富");
		 		ChangeApplicationResult result2 =  project.applyChanges(userId, changeGenerator, descriptionGenerator);
		 		//RenameMap renameMap = result2.getRenameMap();
		 		HashMap<OWLClass, String> hFreshClassList = changeGenerator.getFresshClassList();
		 		OWLDataFactory df = project.getDataFactory();
		 		List<OWLOntologyChange> changeList = new ArrayList<OWLOntologyChange>();
		 		ArrayList<OWLEntity> alRenamedClassList = new ArrayList<OWLEntity>();
		 		for (Entry<OWLClass, String> entry : hFreshClassList.entrySet()) {
		 			OWLClass freshClass = entry.getKey();
		 			String from = entry.getValue();
		 			OWLEntity renamedClass = result2.getRenamedEntity(freshClass);
		 			String annotaionValue= UtilConstants.FLAG_ENRICHED + ": Y" + "; " + UtilConstants.FLAG_FROM + ": " + from;
		 			OWLAnnotation commentAnno = df.getOWLAnnotation(
		 					 df.getRDFSComment(),
		 					 df.getOWLLiteral(annotaionValue, "en"));
		 			
		 			OWLAxiom ax = df.getOWLAnnotationAssertionAxiom(renamedClass.getIRI(), commentAnno);
		 			AddAxiom addAxiom =  new AddAxiom(project.getRootOntology(), ax);	 
		 			changeList.add(addAxiom);
		 			alRenamedClassList.add(renamedClass);
		 		}
		 		project.applyChanges(userId, changeList, "添加annotaion");
		 		for (OWLEntity renamedClass: alRenamedClassList){
		 			String browserText = rm.getBrowserText(renamedClass);
	                String name = renamedClass.getIRI().toString();
	                SubclassEntityData subEntityData = new SubclassEntityData(name, browserText, Collections.<EntityData>emptySet(), 0);
	                subClassEntityDataList.add(subEntityData);
	                OwlClassHolder classHolder = new OwlClassHolder();
	                classHolder.setBrowserText(browserText);
	                classHolder.setName(name);
	                classHolder.setOwlClass((OWLClass)renamedClass);
	                classComparator.setMatchLevel(MatchLevel.CASE_SENSITIVE);
	  			  
	                int pos = Collections.binarySearch(this._alClassByBT, classHolder, classComparator);
	                _alClassByBT.add((pos + 1) * -1, classHolder);
	  			  
	  			  	classComparator.setMatchLevel(MatchLevel.CASE_INSENSITIVE);
	  			  	pos = Collections.binarySearch(this._alClassByLowerBT, classHolder, classComparator);
	  			  	_alClassByLowerBT.add((pos + 1) * -1, classHolder);
		 		} 
		 }
		 
		 private void createObjectProperties(OWLAPIProject project, CreateTriplesAction action,UserId userId, CreateTriplesResult result) {
			 _createdObjectClassList = new ArrayList<SubclassEntityData>();
			 _createdObjectPropertyList = new ArrayList<EntityData>();
			 ArrayList<TripleData> candidateTriples = this.extractObjectProperties(action.getCandidateTriples());
			 OwlClassHolder somethingClassHolder = null;
			 OwlObjectPropertyHolder someObjectPropertyHolder = null;
			 boolean bHasFreshObjectClass = this.checkFreshObjectClasses(candidateTriples);
			 if (bHasFreshObjectClass){
				 somethingClassHolder = this.getSomeThingClass(project, userId);
				 SubclassEntityData somethingClassEntityData = new SubclassEntityData(somethingClassHolder.getName(), somethingClassHolder.getBrowserText(), Collections.<EntityData>emptySet(), 0);
				 result.setSomethingClass(somethingClassEntityData);
			 }
			 boolean bHasFreshObjectProperty = this.checkFreshObjectProperty(candidateTriples);
			 if (bHasFreshObjectProperty){
				 someObjectPropertyHolder = this.getSomeObjectProperty(project, userId);
				 EntityData someOPEntityData = new EntityData(someObjectPropertyHolder.getName(), someObjectPropertyHolder.getBrowserText(), Collections.<EntityData>emptySet());
				 result.setSomeObjectProperty(someOPEntityData);
			 }
			 String currentClassName = action.getEntityName();
			 OwlClassHolder currentClassHolder = this.getClassHolder(currentClassName);
			 List<Triple> currentTriples = this.getEntityTriples(project.getProjectId().getId(), currentClassName);
			 List<TripleData> freshTriples = this.extractFreshTriples(currentTriples, candidateTriples);
			  if (freshTriples!=null && freshTriples.size()>0){
				  int newTripleCount = 0;
				  for (TripleData freshTriple: freshTriples){
					  if (newTripleCount<=_newTriplePerClassCurb){
						  boolean tripleCreated = createNewTriple(project, currentClassHolder, somethingClassHolder, someObjectPropertyHolder, freshTriple, userId);
						  if (tripleCreated){
							  newTripleCount++;
						  }
					  }
				  }
			  }
			 result.setObjectPropertyDataList(_createdObjectPropertyList);
			 result.setObjectClassEntityDataList(_createdObjectClassList);
		 }
		 
		 private boolean createNewTriple(OWLAPIProject project, OwlClassHolder subjectClassHolder, OwlClassHolder newObjectClassParent, OwlObjectPropertyHolder newObjectPropertyHolder, TripleData freshTriple, UserId userId){
			 
			  String predicateBrowserText = freshTriple.getPredicate();
			  String objectBrowserText = freshTriple.getObject();
			  OwlDataPropertyHolder dpHolderSeed = new OwlDataPropertyHolder();
			  dpHolderSeed.setBrowserText(predicateBrowserText);
			  OwlDataPropertyHolderComparator dpComparator = new OwlDataPropertyHolderComparator(MatchLevel.CASE_INSENSITIVE);
			  int pos = Collections.binarySearch(this._alDataProperyByLowerBT, dpHolderSeed, dpComparator);
			  //暂不处理DataProerty;
			  if (pos>=0){
				  return false;
			  }
			  boolean bPropertyExists = false;
			  OwlObjectPropertyHolder targetPropertyHolder = null;
			  pos = -1;
			  OwlObjectPropertyHolder opHolderSeed = new OwlObjectPropertyHolder();
			  opHolderSeed.setBrowserText(predicateBrowserText);
			  OwlObjectPropertyHolderComparator opComparator = new OwlObjectPropertyHolderComparator(MatchLevel.CASE_SENSITIVE);
			  pos = Collections.binarySearch(this._alObjectProperyByBT, opHolderSeed, opComparator);
			  if (pos>=0){
				  bPropertyExists = true;
				  targetPropertyHolder = _alObjectProperyByBT.get(pos);
			  }else{
				  opComparator = new OwlObjectPropertyHolderComparator(MatchLevel.CASE_INSENSITIVE);
				  pos = Collections.binarySearch(this._alObjectProperyByLowerBT, opHolderSeed, opComparator);
				  if (pos>=0){
					  bPropertyExists = true;
					  targetPropertyHolder = _alObjectProperyByLowerBT.get(pos);
				  }
			  }
			  
			  boolean bObjectClassExists = false;
			  OwlClassHolder targetObjectClassHolder = null;
			  pos = -1;
			  OwlClassHolder classHolderSeed = new OwlClassHolder();
			  classHolderSeed.setBrowserText(objectBrowserText);
			  OwlClassHolderComparator classComparator = new OwlClassHolderComparator(MatchLevel.CASE_SENSITIVE);
			  pos = Collections.binarySearch(this._alClassByLowerBT, classHolderSeed, classComparator);
			  if (pos>=0){
				  bObjectClassExists = true;
				  targetObjectClassHolder = _alClassByLowerBT.get(pos);
			  }else{
				  classComparator = new OwlClassHolderComparator(MatchLevel.CASE_INSENSITIVE);
				  pos = Collections.binarySearch(this._alClassByLowerBT, classHolderSeed, classComparator);
				  if (pos>=0){
					  bObjectClassExists = true;
					  targetObjectClassHolder = _alClassByLowerBT.get(pos);
				  }
			  }
			  if ((bPropertyExists == false && this._newPropertyCount>=this._newPropertyCurb) ||
					(bObjectClassExists == false && this._newClassCount>=this._newClassCurb)){
				  return false;
			  }
			  
			  if (bPropertyExists == false){
				  //create property;
				  targetPropertyHolder = this.createNewObjectProperty(project, newObjectPropertyHolder.getOwlObjectProperty(), predicateBrowserText, userId);
				  
				  opComparator.setMatchLevel(MatchLevel.CASE_SENSITIVE);
				  pos = Collections.binarySearch(this._alObjectProperyByBT, targetPropertyHolder, opComparator);
				  _alObjectProperyByBT.add((pos + 1) * -1, targetPropertyHolder);
				  
				  opComparator.setMatchLevel(MatchLevel.CASE_INSENSITIVE);
				  pos = Collections.binarySearch(this._alObjectProperyByLowerBT, targetPropertyHolder, opComparator);
				  _alObjectProperyByLowerBT.add((pos + 1) * -1, targetPropertyHolder);
				  
				  EntityData targetPropertyEntity = new EntityData(targetPropertyHolder.getName(), targetPropertyHolder.getBrowserText(), Collections.<EntityData>emptySet());
				  _createdObjectPropertyList.add(targetPropertyEntity); 
				  			  }
			  if (bObjectClassExists == false){
				  targetObjectClassHolder = this.createNewClass(project, newObjectClassParent.getOwlClass(), objectBrowserText, userId);
				  
				  classComparator.setMatchLevel(MatchLevel.CASE_SENSITIVE);
				  pos = Collections.binarySearch(this._alClassByBT, targetObjectClassHolder, classComparator);
				  _alClassByBT.add((pos + 1) * -1, targetObjectClassHolder);
				  
				  classComparator.setMatchLevel(MatchLevel.CASE_INSENSITIVE);
				  pos = Collections.binarySearch(this._alClassByLowerBT, targetObjectClassHolder, classComparator);
				  _alClassByLowerBT.add((pos + 1) * -1, targetObjectClassHolder);
				  
				  SubclassEntityData objectClassEntityData = new SubclassEntityData(targetObjectClassHolder.getName(), targetObjectClassHolder.getBrowserText(), Collections.<EntityData>emptySet(), 0);
				  _createdObjectClassList.add(objectClassEntityData);
			  }
			  OWLDataFactory df = project.getDataFactory();
			 
			  OWLClassExpression hasSome =
					  df.getOWLObjectSomeValuesFrom(targetPropertyHolder.getOwlObjectProperty(), targetObjectClassHolder.getOwlClass());
			  
			  String from="Document Triples";
			  String annotaionValue= UtilConstants.FLAG_ENRICHED + ": Y" + "; " + UtilConstants.FLAG_FROM + ": " + from;
			  OWLAnnotation commentAnno = df.getOWLAnnotation(
						 df.getRDFSComment(),
						 df.getOWLLiteral(annotaionValue, "en"));
			  Set<OWLAnnotation> sAnnos = new HashSet<OWLAnnotation>();	
			  sAnnos.add(commentAnno);
			  OWLSubClassOfAxiom ax =
					  df.getOWLSubClassOfAxiom(subjectClassHolder.getOwlClass(), hasSome,sAnnos);
			  List<OWLOntologyChange> changeList = new ArrayList<OWLOntologyChange>();	
			  AddAxiom addAxiom =  new AddAxiom(project.getRootOntology(), ax);	 
			  changeList.add(addAxiom);
			  project.applyChanges(userId, changeList, "添加类约束");
			  return true;
		  }
		 private OwlClassHolder createNewClass(OWLAPIProject project, OWLClass parentClass, String browserText, UserId userId){
			  	if (parentClass==null){
			  		parentClass = project.getDataFactory().getOWLThing();
			  	}
			 	OwlClassHolder holder = new OwlClassHolder();
		    	RenderingManager rm = project.getRenderingManager();
		 	    ArrayList<CandidateClassHolder> alCandidateClassHolders = new ArrayList<CandidateClassHolder>();
		 	    CandidateClassHolder candidateClassHolder = new CandidateClassHolder();
		 	    candidateClassHolder.setOwlClass(parentClass);
		 	    ArrayList<CandidateEntity> alCandidateEntities = new ArrayList<CandidateEntity>();
		 	    CandidateEntity candidateEntity = new CandidateEntity();
		 	    candidateEntity.setBrowserText(browserText);
		 	    candidateEntity.setEntityType(UtilEntityType.CLASS);
		 	    candidateEntity.setSourceLabel("Document Triples ");
		 	    alCandidateEntities.add(candidateEntity);
		 	    candidateClassHolder.setCandidateChildClassList(alCandidateEntities);
		 	    alCandidateClassHolders.add(candidateClassHolder);
		 	    CandidateClassesChangeGenerator changeGenerator = new CandidateClassesChangeGenerator(alCandidateClassHolders);
		 		ChangeDescriptionGenerator descriptionGenerator = new FixedMessageChangeDescriptionGenerator("本体丰富");
		 		ChangeApplicationResult<Set<OWLObjectProperty>> result2 =  project.applyChanges(userId, changeGenerator, descriptionGenerator);
		 		//RenameMap renameMap = result2.getRenameMap();
		 		HashMap<OWLClass, String> hFreshClassList = changeGenerator.getFresshClassList();
		 		OWLDataFactory df = project.getDataFactory();
		 		List<OWLOntologyChange> changeList = new ArrayList<OWLOntologyChange>();
		 		ArrayList<OWLEntity> alRenamedClassList = new ArrayList<OWLEntity>();
		 		for (Entry<OWLClass, String> entry : hFreshClassList.entrySet()) {
		 			OWLClass freshClass = entry.getKey();
		 			String from = entry.getValue();
		 			OWLEntity renamedClass = result2.getRenamedEntity(freshClass);
		 			String annotaionValue= UtilConstants.FLAG_ENRICHED + ": Y" + "; " + UtilConstants.FLAG_FROM + ": " + from;
		 			OWLAnnotation commentAnno = df.getOWLAnnotation(
		 					 df.getRDFSComment(),
		 					 df.getOWLLiteral(annotaionValue, "en"));
		 			
		 			OWLAxiom ax = df.getOWLAnnotationAssertionAxiom(renamedClass.getIRI(), commentAnno);
		 			AddAxiom addAxiom =  new AddAxiom(project.getRootOntology(), ax);	 
		 			changeList.add(addAxiom);
		 			alRenamedClassList.add(renamedClass);
		 		}
		 		project.applyChanges(userId, changeList, "添加annotaion");
		 		holder.setBrowserText(browserText);
		 		holder.setName(alRenamedClassList.get(0).getIRI().toString());
		 		holder.setOwlClass((OWLClass)alRenamedClassList.get(0));
		 		this._newClassCount++;
		 		return holder;	
		  }
		 
		 private OwlObjectPropertyHolder createNewObjectProperty(OWLAPIProject project, OWLObjectProperty parentProperty, String browserText, UserId userId){
			  	OwlObjectPropertyHolder holder = new OwlObjectPropertyHolder();
		    	RenderingManager rm = project.getRenderingManager();
		    	if (parentProperty==null){
		    		parentProperty = project.getDataFactory().getOWLTopObjectProperty();
		    	}
		 	    
		 	    
		 	    ArrayList<CandidateEntity> alCandidateEntities = new ArrayList<CandidateEntity>();
		 	    CandidateEntity candidateEntity = new CandidateEntity();
		 	    candidateEntity.setBrowserText(browserText);
		 	    candidateEntity.setEntityType(UtilEntityType.OBJECT_PROPERTY);
		 	    candidateEntity.setSourceLabel("Document Triples ");
		 	    alCandidateEntities.add(candidateEntity);
		 	   
		 	    CandidateOPChangeGenerator changeGenerator = new CandidateOPChangeGenerator(parentProperty, alCandidateEntities);
		 		ChangeDescriptionGenerator descriptionGenerator = new FixedMessageChangeDescriptionGenerator("新对象属性");
		 		ChangeApplicationResult result2 =  project.applyChanges(userId, changeGenerator, descriptionGenerator);
		 		//RenameMap renameMap = result2.getRenameMap();
		 		HashMap<OWLObjectProperty, String> hFreshPropertyList = changeGenerator.getFresshPropertyList();
		 		OWLDataFactory df = project.getDataFactory();
		 		List<OWLOntologyChange> changeList = new ArrayList<OWLOntologyChange>();
		 		ArrayList<OWLEntity> alRenamedPropertyList = new ArrayList<OWLEntity>();
		 		for (Entry<OWLObjectProperty, String> entry : hFreshPropertyList.entrySet()) {
		 			OWLObjectProperty freshProperty = entry.getKey();
		 			String from = entry.getValue();
		 			OWLEntity renamedProperty = result2.getRenamedEntity(freshProperty);
		 			String annotaionValue= UtilConstants.FLAG_ENRICHED + ": Y" + "; " + UtilConstants.FLAG_FROM + ": " + from;
		 			OWLAnnotation commentAnno = df.getOWLAnnotation(
		 					 df.getRDFSComment(),
		 					 df.getOWLLiteral(annotaionValue, "en"));
		 			
		 			OWLAxiom ax = df.getOWLAnnotationAssertionAxiom(renamedProperty.getIRI(), commentAnno);
		 			AddAxiom addAxiom =  new AddAxiom(project.getRootOntology(), ax);	 
		 			changeList.add(addAxiom);
		 			alRenamedPropertyList.add(renamedProperty);
		 		}
		 		project.applyChanges(userId, changeList, "添加annotaion");
		 		holder.setBrowserText(browserText);
		 		holder.setName(alRenamedPropertyList.get(0).getIRI().toString());
		 		holder.setOwlObjectProperty((OWLObjectProperty)alRenamedPropertyList.get(0));
		 		this._newPropertyCount++;
		 		return holder;	
		  }
		 
		 
		 
		 private OwlClassHolder getClassHolder(String className){
			 for (OwlClassHolder classHolder: this._alClassByBT){
				 if (classHolder.getName().compareTo(className)==0){
					 return classHolder;
				 }
			 }
			 return null;
		 } 
		 private List<TripleData> extractFreshTriples(List<Triple> currentTriples, List<TripleData> candidateTriples){
			  List<TripleData> alFreshTripleData = new ArrayList<TripleData>();
			  for (TripleData candidateTriple: candidateTriples){
				  boolean bExists = false;
				  for (Triple currentTriple: currentTriples){
					  if (currentTriple.getProperty().getBrowserText().equalsIgnoreCase(candidateTriple.getPredicate())
						&& currentTriple.getValue().getBrowserText().equalsIgnoreCase(candidateTriple.getObject())
							  ){
						  bExists = true;
					  }
				  }
				  if (bExists==false){
					  alFreshTripleData.add(candidateTriple);
				  }
			  }
			  return alFreshTripleData;
		  } 
		 public List<Triple> getEntityTriples(final String projectName, String entityName) {
		        final Set<Triple> result = new LinkedHashSet<Triple>();
		        TripleMapperSelector selector = new TripleMapperSelector(getProject(projectName), AnnotationsTreatment.EXCLUDE_ANNOTATIONS, NonAnnotationTreatment.INCLUDE_NON_ANNOTATIONS);
		        OWLAPIProject project = getProject(projectName);
		        Set<OWLEntity> entities = project.getRenderingManager().getEntities(entityName);
		        for (OWLEntity entity : entities) {
		            TripleMapper<?> mapper = selector.getMapper(entity);
		            if (mapper != null) {
		                result.addAll(mapper.getTriples());
		            }
		        }
		        return new ArrayList<Triple>(result);
		  }
		 
		 private boolean checkFreshObjectClasses(List<TripleData> tripleList){
			 OwlClassHolderComparator classComparator = new OwlClassHolderComparator(MatchLevel.CASE_INSENSITIVE);
			 for (TripleData triple: tripleList){
				 OwlClassHolder classHolderSeed = new OwlClassHolder();
				 classHolderSeed.setBrowserText(triple.getObject());
				 int pos = Collections.binarySearch(this._alClassByLowerBT, classHolderSeed, classComparator);
				 if (pos<0){
					 return true;
				 }
			 }
			 return false;
		 }
		 private OwlClassHolder getSomeThingClass(OWLAPIProject project, UserId userId){
			 OwlClassHolderComparator classComparator = new OwlClassHolderComparator(MatchLevel.CASE_SENSITIVE);
			 OwlClassHolder classHolderSeed = new OwlClassHolder();
			 classHolderSeed.setBrowserText(UtilConstants.CLASS_SOMETHING);
			 int pos = Collections.binarySearch(this._alClassByBT, classHolderSeed, classComparator);
			 if (pos>=0){
				 return _alClassByBT.get(pos);
			 }
			 
			 //create something class
			 return this.createNewClass(project, null, UtilConstants.CLASS_SOMETHING, userId);
		 }
		 
		 private boolean checkFreshObjectProperty(List<TripleData> tripleList){
			
			  OwlDataPropertyHolderComparator dpComparator = new OwlDataPropertyHolderComparator(MatchLevel.CASE_INSENSITIVE);
			  OwlObjectPropertyHolderComparator opComparator = new OwlObjectPropertyHolderComparator(MatchLevel.CASE_INSENSITIVE);
			 
			  
			 for (TripleData triple: tripleList){
				 String predicateBrowserText = triple.getPredicate();
				 OwlDataPropertyHolder dpHolderSeed = new OwlDataPropertyHolder();
				 dpHolderSeed.setBrowserText(predicateBrowserText);
				 int pos = Collections.binarySearch(this._alDataProperyByLowerBT, dpHolderSeed, dpComparator);
				  //暂不处理DataProerty;
				  if (pos>=0){
					  continue;
				  }
				  pos = -1;
				  OwlObjectPropertyHolder opHolderSeed = new OwlObjectPropertyHolder();
				  opHolderSeed.setBrowserText(predicateBrowserText);
				  pos = Collections.binarySearch(this._alObjectProperyByLowerBT, opHolderSeed, opComparator);
				  if (pos<0){
					  return true;
				  }	  
			 }
			 return false;
		 }
		
		 private OwlObjectPropertyHolder getSomeObjectProperty(OWLAPIProject project, UserId userId){
			 OwlObjectPropertyHolderComparator opComparator = new OwlObjectPropertyHolderComparator(MatchLevel.CASE_SENSITIVE);
			 OwlObjectPropertyHolder opHolderSeed = new OwlObjectPropertyHolder();
			  opHolderSeed.setBrowserText(UtilConstants.OP_SOME_OBJECT_PROPERTY);
			  int pos = Collections.binarySearch(this._alObjectProperyByBT, opHolderSeed, opComparator);
			  if (pos>=0){
				  return _alObjectProperyByBT.get(pos);
			  }	 
			 
			 //create something class
			 return this.createNewObjectProperty(project, null, UtilConstants.OP_SOME_OBJECT_PROPERTY, userId);
		 }
		 
	     public CreateTriplesResult execute(String projectName, CreateTriplesAction action,UserId userId) {
	    	CreateTriplesResult result = new CreateTriplesResult();
	    	OWLAPIProject project = this.getProject(projectName);
	    	loadClassHolders(project);
			loadDataPropertyHolders(project);
			loadObjectPropertyHolders(project);
	    	createSubclasses(project, action, userId, result);
	    	createObjectProperties(project, action, userId, result);
	    	EnrichmentResult result1 = new EnrichmentResult();
	    	EntityCounter entityCounter = new EntityCounter();
			StatisticsResult result2 = entityCounter.countEntities(projectName);
			result1.setEnrichedClassNumber(result2.getEnrichedClassNumber());
			result1.setEnrichedPropertyNumber(result2.getEnrichedPropertyNumber());
			result1.setOriginalClassNumber(result2.getOriginalClassNumber());
			result1.setOriginalPropertyNumber(result2.getOriginalPropertyNumber());
			result1.setTotalClassNumber(result2.getTotalClassNumber());
			result1.setTotalPropertyNumber(result2.getTotalPropertyNumber());
			result.setEnrichmentResult(result1);
			
	        return result;
	    }
	     
	    private  ArrayList<CandidateEntity> extractSubclassCandidates(List<TripleData> tripleList){
	    	ArrayList<CandidateEntity> subclasses = new ArrayList<CandidateEntity>();
	    	for (TripleData tripleData: tripleList){
	    		if (tripleData.getPredicate().compareTo(UtilConstants.REL_HAS_SUBCLASS)==0){
	    			CandidateEntity subclass = new CandidateEntity();
	    			subclass.setBrowserText(tripleData.getObject());
	    			subclass.setEntityType(UtilEntityType.CLASS);
	    			subclass.setSourceLabel(tripleData.getSourceName());
	    			subclasses.add(subclass);
	    		}
	    	}
	    	return subclasses;
	    }
	    
	    private  ArrayList<TripleData> extractObjectProperties(List<TripleData> tripleList){
	    	ArrayList<TripleData> result = new ArrayList<TripleData>();
	    	for (TripleData tripleData: tripleList){
	    		if (tripleData.getPredicate().compareTo(UtilConstants.REL_HAS_SUBCLASS)!=0){
	    			result.add(tripleData);
	    		}
	    	}
	    	return result;
	    }
	    
	    private void loadClassHolders(OWLAPIProject project){
			  _alClassByBT = new ArrayList<OwlClassHolder>();
			  _alClassByLowerBT = new ArrayList<OwlClassHolder>();
			  RenderingManager rm = project.getRenderingManager();
			  Set<OWLClass> sClassList = project.getRootOntology().getClassesInSignature();
			
			  for (OWLClass cls: sClassList){
				  String browserText = rm.getBrowserText(cls);
				  OwlClassHolder holder = new OwlClassHolder();
				  holder.setBrowserText(browserText);
				  holder.setName(cls.getIRI().toString());
				  holder.setOwlClass(cls);
				  _alClassByBT.add(holder);
				  _alClassByLowerBT.add(holder);
			  }
			  OwlClassHolderComparator comparator = new OwlClassHolderComparator(MatchLevel.CASE_SENSITIVE);
			  Collections.sort(_alClassByBT, comparator);
			  comparator = new OwlClassHolderComparator(MatchLevel.CASE_INSENSITIVE);
			  Collections.sort(_alClassByLowerBT, comparator);
			 
		  }
		  private void loadDataPropertyHolders( OWLAPIProject project){
			  _alDataProperyByBT = new ArrayList<OwlDataPropertyHolder>();
			  _alDataProperyByLowerBT = new ArrayList<OwlDataPropertyHolder>();
			  RenderingManager rm = project.getRenderingManager();
			  Set<OWLDataProperty> sPropertyList = project.getRootOntology().getDataPropertiesInSignature();
			  for (OWLDataProperty property: sPropertyList){
				  OwlDataPropertyHolder holder = new OwlDataPropertyHolder();
				  String entityName = property.getIRI().toString();
				  String browserText = rm.getBrowserText(property);
				  holder.setBrowserText(browserText);
				  holder.setName(entityName);
				  holder.setOwlDataProperty(property);
				  this._alDataProperyByBT.add(holder);
				  this._alDataProperyByLowerBT.add(holder);
			  }
			  OwlDataPropertyHolderComparator comparator = new OwlDataPropertyHolderComparator(MatchLevel.CASE_SENSITIVE);
			  Collections.sort(_alDataProperyByBT, comparator);
			  comparator = new OwlDataPropertyHolderComparator(MatchLevel.CASE_INSENSITIVE);
			  Collections.sort(_alDataProperyByLowerBT, comparator);	  
		  }
		  
		  private void loadObjectPropertyHolders(OWLAPIProject project){
			  this._alObjectProperyByBT = new ArrayList<OwlObjectPropertyHolder>();
			  this._alObjectProperyByLowerBT = new ArrayList<OwlObjectPropertyHolder>();
			  RenderingManager rm = project.getRenderingManager();
			  Set<OWLObjectProperty> sPropertyList = project.getRootOntology().getObjectPropertiesInSignature();
			  for (OWLObjectProperty property: sPropertyList){
				  OwlObjectPropertyHolder holder = new OwlObjectPropertyHolder();
				  String entityName = property.getIRI().toString();
				  String browserText = rm.getBrowserText(property);
				  holder.setBrowserText(browserText);
				  holder.setName(entityName);
				  holder.setOwlObjectProperty(property);;
				  this._alObjectProperyByBT.add(holder);
				  this._alObjectProperyByLowerBT.add(holder);
			  }
			  OwlObjectPropertyHolderComparator comparator = new OwlObjectPropertyHolderComparator(MatchLevel.CASE_SENSITIVE);
			  Collections.sort(_alObjectProperyByBT, comparator);
			  comparator = new OwlObjectPropertyHolderComparator(MatchLevel.CASE_INSENSITIVE);
			  Collections.sort(_alObjectProperyByLowerBT, comparator);
		  }
	   
	}
